#include <windows.h>
#include <stdio.h>
#include "resource.h"
#include "image.h"
#include "data.h"
#include "api.h"
#include "colorswnd.h"
#include "colordlg.h"

#define COLOR_LABEL_PATTERN "RGB %02X%02X%02X INTENSE %d"

typedef struct _COLORDLG_ {
	int rColor;
	int gColor;
	int bColor;
	int intense;
	int captured;
	PCOLORENTRY color;
	COLORREF realColor;
} *PCOLORDLG, COLORDLG;

RECT rcColor = {5, 5, 35, 34};
RECT rcOldColor = {5, 35, 35, 64};

extern PDATA data;

void colorDlgRectColor(HDC pdc, RECT *rect, COLORREF color){
	HBRUSH brColor = CreateSolidBrush(color);
	FillRect(pdc, rect, brColor);	
	DeleteObject(brColor);
}

void colorDlgPaint(HWND hwnd, HDC pdc, PCOLORDLG data){
	int realR = data->rColor;
	int realG = data->gColor;
	int realB = data->bColor;
	int intense;
	if (data->intense>0){
		intense = data->intense;
		realR = (255*intense + realR*(100-intense))/100;
		realG = (255*intense + realG*(100-intense))/100;
		realB = (255*intense + realB*(100-intense))/100;
	}else if (data->intense<0){
		intense = -data->intense;
		realR = (realR*(100-intense))/100;
		realG = (realG*(100-intense))/100;
		realB = (realB*(100-intense))/100;
	}
	data->realColor = RGB(realR, realG, realB);
	colorDlgRectColor(pdc, &rcColor, data->realColor);
	colorDlgRectColor(pdc, &rcOldColor, data->color->color);
}

void colorDlg_drawColor(HWND hwnd, PCOLORDLG data){	
	HDC pdc = GetDC(hwnd);
	colorDlgPaint(hwnd, pdc, data);
	ReleaseDC(hwnd, pdc);
}

void colorDlgSetLabel(HWND hwnd, PCOLORDLG data){
	char label[200];
	sprintf(label, COLOR_LABEL_PATTERN, data->rColor, data->gColor, data->bColor, data->intense);
	SetDlgItemText(hwnd, IDC_COLORLABEL, label);
}

void colorDlgRefreshColor(HWND hwnd, PCOLORDLG data){	
	data->rColor = SendDlgItemMessage(hwnd, IDC_SBRED, SBM_GETPOS, 0, 0);
	data->gColor = SendDlgItemMessage(hwnd, IDC_SBGREEN, SBM_GETPOS, 0, 0);
	data->bColor = SendDlgItemMessage(hwnd, IDC_SBBLUE, SBM_GETPOS, 0, 0);
	data->intense = SendDlgItemMessage(hwnd, IDC_SBINTENSE, SBM_GETPOS, 0, 0)-100;
	colorDlgSetLabel(hwnd, data);
	colorDlg_drawColor(hwnd, data);
}

void colorDlgInitScroller(HWND hwnd, UINT scrollId, int pos, int ini, int end){
	SendDlgItemMessage(hwnd, scrollId, SBM_SETRANGE, ini, end);
	SendDlgItemMessage(hwnd, scrollId, SBM_SETPOS, (WPARAM)pos, TRUE);
}

void colorDlgSetScrolls(HWND hwnd, PCOLORDLG data){
	colorDlgInitScroller(hwnd, IDC_SBRED, data->rColor, 0, 255);
	colorDlgInitScroller(hwnd, IDC_SBGREEN, data->gColor, 0, 255);
	colorDlgInitScroller(hwnd, IDC_SBBLUE, data->bColor, 0, 255);
	colorDlgInitScroller(hwnd, IDC_SBINTENSE, data->intense+100, 0, 200);
}

void colorDlgLButtonDown(HWND hwnd, LPARAM lParam, PCOLORDLG data){
	POINT p = {LOWORD(lParam), HIWORD(lParam)};
	if (PtInRect(&rcColor, p)){
		data->captured = TRUE;
		SetCapture(hwnd);
	}
}

void colorDlgGetColor(HWND hwnd, LPARAM lParam, PCOLORDLG data){
	short x = LOWORD(lParam);
	short y = HIWORD(lParam);
	POINT p = {x, y};
	ClientToScreen(hwnd, &p);
	HDC pdc = GetDC(NULL);
	COLORREF color = GetPixel(pdc, p.x, p.y);
	ReleaseDC(NULL, pdc);
	if (color==CLR_INVALID) return;
	data->rColor = GetRValue(color);
	data->gColor = GetGValue(color);
	data->bColor = GetBValue(color);
	colorDlgSetScrolls(hwnd, data);
	colorDlgSetLabel(hwnd, data);
	colorDlg_drawColor(hwnd, data);
}

void colorDlgLButtonUp(HWND hwnd, LPARAM lParam, PCOLORDLG data){	
	if (data->captured){
		ReleaseCapture();
		data->captured = FALSE;
		colorDlgGetColor(hwnd, lParam, data);
	}
}

int _stdcall colorDlg_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	PCOLORDLG data = (PCOLORDLG)GetWindowLong(hwnd, GWL_USERDATA);
	switch(message){
	case WM_INITDIALOG:
		data = (PCOLORDLG)lParam;
		data->rColor = GetRValue(data->color->color);
		data->gColor = GetGValue(data->color->color);
		data->bColor = GetBValue(data->color->color);
		colorDlgSetScrolls(hwnd, data);
		colorDlgSetLabel(hwnd, data);
		SetWindowLong(hwnd, GWL_USERDATA, lParam);
		SetWindowPos(hwnd, NULL, ::data->config->colordlgpx, ::data->config->colordlgpy, 0, 0, SWP_NOSIZE);
		break;
	case WM_PAINT:
		ON_PAINT(colorDlgPaint);
		break;
	case WM_LBUTTONDOWN:
		colorDlgLButtonDown(hwnd, lParam, data);
		break;
	case WM_NCLBUTTONUP:
	case WM_LBUTTONUP:
		colorDlgLButtonUp(hwnd, lParam, data);
		break;
	case WM_MOUSEMOVE:
		if (data->captured){
			colorDlgGetColor(hwnd, lParam, data);
		}
		break;
	case WM_COMMAND:
		switch(wParam){
		case IDOK:
			data->color->color = data->realColor;
		case IDCANCEL:
			EndDialog(hwnd, wParam);
			break;
		}
		break;
	case WM_HSCROLL:
		switch(LOWORD(wParam))
		{
		case SB_THUMBTRACK:
			SendMessage((HWND)lParam, SBM_SETPOS, HIWORD(wParam), FALSE);
			colorDlgRefreshColor(hwnd, data);
			break;
		}
		break;
	case WM_MOVE:
		::data->config->colordlgpx = LOWORD(lParam);
		::data->config->colordlgpy = HIWORD(lParam);
		break;
	}
	return 0;
}

BOOL colorDlgSelectColor(HWND parentWnd, PCOLORENTRY color)
{
	NEW_DATA(COLORDLG);

	data->color = color;

	HINSTANCE instancia = (HINSTANCE)GetWindowLong(parentWnd, GWL_HINSTANCE);

	BOOL res = DialogBoxParam(instancia, MAKEINTRESOURCE(IDD_COLOR), parentWnd, colorDlg_proc, (DWORD)data);

	FREE_DATA();

	return res;
}